home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
PCW_C.ARJ
/
PCINT24A.ASM
< prev
next >
Wrap
Assembly Source File
|
1991-12-16
|
11KB
|
210 lines
Page ,132
;****************************************************************
;* File Id. Int24a.Asm *
;* Author. Stan Milam. *
;* Date Written. 11/05/89. *
;* *
;* (c) Copyright 1989, 1990 by Stan Milam *
;* *
;* Comments: This code will act as an interrupt handler for *
;* interrupt 24, the DOS Critical Interrupt. It will preserve *
;* the stack, restore the applications DS & ES register and pass*
;* information about the critical error to a C function that *
;* will use a pop-up menu window to give information and accept *
;* input to the user. *
;* *
;* Added code to switch stacks to allow interrupt to be called *
;* by a child process. Stack at time of DOS interrupt is stored*
;* at offset 0x2e of Program Segment Prefix. *
;* Added code to FAIL the operation when return code is 3 even *
;* in DOS versions before 3.1. *
;* *
;* If C function returns -1 (0xffff) we must call the original *
;* Int 24. *
;* *
;* Research material: *
;* PC Tech Journal, April 1987, Exception Handling *
;* Advanced MS-DOS, Second Edition, by Ray Duncan *
;* MS-DOS Encyclopedia *
;****************************************************************
;
Dosseg ;Declare Normal Segmentation
IFDEF POWERC
.Model Large ;Large Model for Power C
ELSE
.Model Large,C ;And Turbo & MSC
ENDIF
Extrn old_int24:Dword ;Address of old interrupt
Extrn _psp:Word ;Segment Address of PSP
.Code
Extrn Critical_Interrupt:Far
;
; Declare storage in the code segment to save ES & DS
;
old_es Dw 0
old_ds Dw 0
save_ss Dw ?
save_sp Dw ?
Page
;
;****************************************************************
;* Int24 *
;* *
;* This routine will be entered when interrupt 24 is generated *
;* by DOS. *
;* *
;* Major Goals: Save stack, Restore application DS & ES, push *
;* information on stack & call C routine, return to DOS with *
;* return information in AX *
;* If -1 (0xffff) is returned by C routine then restore regs & *
;* invoke the original INT 24 handler. *
;****************************************************************
;
Public Int24
Int24 Proc Far
Push Bp ;Set up the stack frame
Mov Bp,Sp
Push Ds ;Preserve the registers
Push Es
Push Bx
Push Cx
Mov Cx,[Bp] ;Save Bp because we swithc stacks
IFDEF POWERC
Push Cs:[old_ds] ;Restore Data Segment
Pop Ds
Mov Bx,_psp ;Get PSP Address in Es so
Mov Es,Bx ;We can switch stacks.
ELSE
Mov Bx,@Data ;This the way we restore DS &
Mov Ds,Bx ;get the PSP address in Turbo C
Mov Bx,Seg _psp ;and Microsoft C.
Mov Es,Bx ;This method accomodates all of
Mov Bx,Es:[_psp] ;the different memory models.
Mov Es,Bx
ENDIF
Mov Cs:[save_ss],Ss ;Save Stack address in Code Seg
Mov Cs:[save_sp],Sp ;So we can switch
Mov Ss,Es:[30h] ;Switch stacks, this allows
Mov Sp,Es:[2eh] ;Child process to use interrupt
Sub Sp,0eh ;Protect Stack if not child
Sti ;Start Interrupts
Push Dx ;Now save every thing else
Push Si
Push Di
;
;These next 4 pushes are parms to C function
;
Push Cx ;Bp:Si is far pointer to
Push Si ;Device Header
Push Di ;Di & Ax are parms to C
Push Ax ;routine. Info passed by DOS.
Call Critical_Interrupt ;Call C routine
Cli ;Turn off interrupts
Cmp Ax,0FFFFh ;Was -1 returned?
Jne Norm_Exit ;No, so return with value in Ax
Page
;
;**************************************************************
;* This part of the code is going to call the orininal INT 24 *
;* To do this we must maintain Ds & Es becuase the pointer to *
;* the old INT 24 is stored in the Data Segment of our *
;* program. However, we restore all other registers. Notice *
;* the strange manipulations of the stack that had to be made *
;* to preserve Ds & Es. *
;**************************************************************
;
IFDEF POWERC
Push Ds ;Force Es & DS to be same
Pop Es ;To point at old interrupt
ELSE
Mov Ax,Seg old_int24 ;Get Segment address for
Mov Es,Ax ;Old interrupt
ENDIF
Pop Ax ;Else restore registers as they
Add Sp,+6 ;were upon entry and call the
Pop Di ;original INT 24 handler (Except
Pop Si ;for Es & Ds)
Pop Dx
Mov Ss,Cs:[save_ss] ;Switch stacks back
Mov Sp,Cs:[save_sp]
Pop Cx ;
Pop Bx
Mov Sp,Bp
Pop Bp ;Restored everything but Ds & Es
Sub Sp,+6 ;Save Bp,Es,Ds
Pushf ;Push flags to fake an interrupt
Call Es:Dword Ptr old_int24 ;Call to old INT 24
Pop Es ;Finally, Restore Ds & Es!
Pop Ds
Pop Bp
Jmp Exit
Norm_Exit:
Mov Bx,Ax ;Restore Ah to the way it was
Pop Ax ;When we entered leaving return
Mov Al,Bl ;Code in Al.
Add Sp,+6 ;Remove Parms to C code
Pop Di ;Restore Registers but return
Pop Si ;User action in Ax
Pop Dx
Mov Ss,Cs:[save_ss] ;Switch stacks back
Mov Sp,Cs:[save_sp]
Pop Cx ;Be sure to restore these
Pop Bx
Pop Es
Pop Ds
Mov Sp,Bp
Pop Bp
Exit:
Cmp Al,3 ;Was it a FAIL request?
Je Fail ;Yes it was
Iret ;Not a FAIL--Return to Dos
Page
;
;**************************************************************
;* FAIL *
;* *
;* Since the FAIL option does not exist in versions of DOS *
;* before 3.1 I have written my own fail operation. Simply *
;* restores registers, move 0xffff into Ax (?), set the carry *
;* flag, and RET 2 back to the interrupted program. *
;**************************************************************
;
Fail: Add Sp,6 ;Remove DOS return address
Pop Bx ;Restore program registers
Pop Bx
Pop Cx
Pop Dx
Pop Si
Pop Di
Pop Bp
Pop Ds
Pop Es
Mov Ax,0ffffh ;Error return code
Stc ;Set Carry flag
Sti ;Start interrupts again
Ret 2 ;Return to DOS remove Flags
Int24 Endp
IFDEF POWERC
Page
;
;********************************************************************
;* _Save_ES_DS_ *
;* *
;* Here we save Es & Ds values in the Code Segment so we can re- *
;* trieve and restore them when the interrupt occurs. If we do not *
;* reset these registers our C code will not work. This routine is *
;* called by the installation routine set_int24(). *
;********************************************************************
;
Public _Save_ES_DS_
_Save_ES_DS_ Proc Far
Push Es ;Save Es on Stack
Pop Cs:[old_es] ;Pop it into our Code Segment
Push Ds ;Same thing with Ds
Pop Cs:[old_ds]
Ret
_Save_ES_DS_ Endp
ENDIF
End